import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.family'] = "SimHei"

def softmax(logits):
    exp_logits = np.exp(logits)
    return exp_logits / np.sum(exp_logits, axis=1, keepdims=True)

def sparse_categorical_crossentropy(y_true, logits):
    num_samples = y_true.shape[0]
    y_pred = softmax(logits)
    loss = -np.log(y_pred[range(num_samples), y_true])
    return loss.mean()

fashion_mnist = tf.keras.datasets.fashion_mnist
(train_x,train_y),(test_x,test_y) = fashion_mnist.load_data()
names = ['T-shirt/top','Trouser','Pullover','Dress','Coat','Sandal','Shirt','Sneaker','Bag','Ankle book']

#对属性进行归一化，使取值范围在0-1之间，同时转换为tensor张量，标签值转换为张量，0-9之间的整数
X_train,X_test = tf.cast(train_x / 255.0,tf.float32),tf.cast(test_x / 255.0,tf.float32)
Y_train,Y_test = tf.cast(train_y,tf.int16),tf.cast(test_y,tf.int16)

#建立Sequential模型，使用add方法添加层
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28))) #Flatten不进行计算，将输入的二维数组转换为一维数组
model.add(tf.keras.layers.Dense(128,activation="relu")) #添加隐含层，隐含层是全连接层，128个结点，激活函数使用relu函数
model.add(tf.keras.layers.Dense(10,activation="softmax")) #添加输出层，输出层是全连接层，激活函数是softmax函数

#配置训练方法
#优化器使用adam，损失函数使用稀疏交叉熵损失函数，准确率使用稀疏分类准确率函数
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['sparse_categorical_accuracy'])


#训练模型
#使用训练集中的数据训练，从中划分20%作为测试数据，用在每轮训练后评价模型的性能，每个小批量使用64条数据，训练5轮
model.fit(X_train,Y_train,batch_size=64,epochs=5,validation_split=0.2)

#使用测试集评估模型，verbose = 2表示每一轮输出一行记录
model.evaluate(X_test,Y_test,verbose=2)

#使用模型
for i in range(4):
    num = np.random.randint(1,10000)

    plt.subplot(1,4,i + 1)
    plt.axis("off")
    plt.imshow(test_x[num],cmap="gray")
    y_pred = np.argmax(model.predict(test_x[num].reshape(1,28,28)))
    plt.title("原值:"+names[test_y[num]]+"\n预测值"+ names[y_pred])

plt.show()
